package com.utilities.parsers.ecocyc.classesParser;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class GoTreeConstructor extends ParseListener
{
	private HashMap<String, String> geneNamesToIdMap = null;
	private HashMap<String, String> classIdToDescriptionMap = null;
	private String id = null;
	private String type = null;
	private String commonName = null;
	private String inputFile = "C:/Users/bansalp/database/ecocycData/14.5/data/genes.dat";
	private String dataFile = "C:/Users/bansalp/database/ecocycData/14.5/data/gene_associations.ecocyc";
	private String pathwayFile = "C:/Users/bansalp/database/ecocycData/14.5/data/pathways.col";
	private String pathwayDatFile =  "C:/Users/bansalp/database/ecocycData/14.5/data/pathways.dat";
	private String outFile = "C:/Users/bansalp/database/geneMapping4.dat";
	private String errorFile = "C:/Users/bansalp/database/error.dat";
	private String pathwayInfo = "C:/Users/bansalp/database/pathwayInfo.dat";
	private String rxnCompoundMap = "C:/Users/bansalp/database/rxnCmp.dat";
	private String classesDefinitionInputFile = "C:/Users/bansalp/database/ecocycData/14.5/data/classes.dat";
	private String rxnsDatFile =  "C:/Users/bansalp/database/ecocycData/14.5/data/reactions.dat";
	
	private boolean flag = true;
	
	
	public static void main(String[] args) throws IOException
	{
		GoTreeConstructor constructor = new GoTreeConstructor();
		ParseClassFileParser classFileParser = new ParseClassFileParser();
		classFileParser.addListener(constructor);
		classFileParser.parse(new File(constructor.inputFile));
		constructor.flag = false;
		classFileParser.parse(new File(constructor.classesDefinitionInputFile));
		constructor.readDataFile();
	}
	
	private void readDataFile() throws IOException 
	{
		HashMap<String, ArrayList<String>> geneIdToGo = getGeneIdToGoIdMap();
		HashMap<String, ArrayList<String>> pathwayIdtoGeneId = pathwayIdToGeneId();
		HashMap<String, ArrayList<String>> pathwayToRxns = getPathwayToRxnMap();
		HashMap<String, ArrayList<String>> rxnsToCompounds = getRxnToCmpdsMap();
		
		PrintWriter printWriter2 = new PrintWriter(errorFile);
		PrintWriter printWriter = new PrintWriter(outFile);
		Set<String> set = pathwayIdtoGeneId.keySet();
		for(String key : set)
		{
			StringBuffer buffer = new StringBuffer();
			ArrayList<String> geneIds = pathwayIdtoGeneId.get(key);
			for(String geneId : geneIds)
			{
				ArrayList<String> goIds = geneIdToGo.get(geneId);
				if (goIds == null)
				{
//					System.out.println(geneId);
					printWriter2.println(geneId);
				}
				else
				{
					for(String goId : goIds)
					{
						String description = classIdToDescriptionMap.get(goId);
						if (description == null)
						{
							System.out.println("Description for go id " + goId + " not found" );
							buffer.append(goId + " ");
						}
						else
						{
							buffer.append(goId + " " + description + " ");
						}
						
					}
				}
			}
			printWriter.println(key + "\t" + buffer.toString());
		}
		printWriter.flush();
		printWriter.close();
		printWriter2.flush();
		printWriter2.close();
		
		printWriter2 = new PrintWriter(pathwayInfo);
		Set<String> keySet = pathwayToRxns.keySet();
		for(String key : keySet)
		{
			StringBuffer buffer = new StringBuffer();
			ArrayList<String> rxns = pathwayToRxns.get(key);
			for(String rxn : rxns)
			{
				buffer.append(rxn + " ");
			}
			printWriter2.println(key + " " + buffer.toString());
			buffer = new StringBuffer();
		}
		printWriter2.flush();
		printWriter2.close();
		
		printWriter2 = new PrintWriter(rxnCompoundMap);
		keySet = rxnsToCompounds.keySet();
		for(String key : keySet)
		{
			StringBuffer buffer = new StringBuffer();
			ArrayList<String> rxns = rxnsToCompounds.get(key);
			String[] params = rxns.get(0).split("#####");
			for(String param : params)
			{
				if (!param.trim().equalsIgnoreCase(""))
				{
					buffer.append(param + " ");
				}
			}
			params = rxns.get(1).split("#####");
			for(String param : params)
			{
				if (!param.trim().equalsIgnoreCase(""))
				{
					buffer.append(param + " ");
				}
			}
			printWriter2.println(key + " " + buffer.toString());
			buffer = new StringBuffer();
		}
		printWriter2.flush();
		printWriter2.close();
		
	}

	private HashMap<String, ArrayList<String>> getRxnToCmpdsMap() throws IOException {
		HashMap<String, ArrayList<String>> rxnsToCompounds = new HashMap<String, ArrayList<String>>();
		BufferedReader bufferedReader = new BufferedReader(new FileReader(rxnsDatFile));;
		String readLine = bufferedReader.readLine();
		String id_temp = null;
		ArrayList<String> cmpds_temp = new ArrayList<String>();
		StringBuffer left = new StringBuffer();
		StringBuffer right = new StringBuffer();
		while(readLine != null)
		{
			if (readLine.startsWith("UNIQUE-ID"))
			{
				id_temp = readLine.split("UNIQUE-ID -")[1].trim();
			}
			else if (readLine.startsWith("REACTION-LIST"))
			{
				cmpds_temp.add(readLine.split("REACTION-LIST -")[1].trim());
			}
			else if (readLine.startsWith("LEFT -"))
			{
				left.append(readLine.split("LEFT -")[1].trim()+ "#####");
			}
			else if (readLine.startsWith("RIGHT -"))
			{
				right.append(readLine.split("RIGHT -")[1].trim()+ "#####");
			}
			else if (readLine.startsWith("//"))
			{
				if (rxnsToCompounds.containsKey(id_temp))
				{
					System.out.println("rxn id encountered twice " + id_temp);
					System.exit(1);
				}
				cmpds_temp.add(left.toString());
				cmpds_temp.add(right.toString());
				rxnsToCompounds.put(id_temp, cmpds_temp);
				id_temp = null;
				cmpds_temp = new ArrayList<String>();
				left = new StringBuffer();
				right = new StringBuffer();
			}
			readLine = bufferedReader.readLine();
		}
		bufferedReader.close();
		return rxnsToCompounds;
	}

	private HashMap<String, ArrayList<String>> getGeneIdToGoIdMap()
			throws FileNotFoundException, IOException {
		BufferedReader bufferedReader = new BufferedReader(new FileReader(dataFile));
		String readLine = bufferedReader.readLine();
		HashMap<String, ArrayList<String>> geneIdToGo = new HashMap<String, ArrayList<String>>();
		while(readLine != null)
		{
			String[] params = readLine.split("\t");
			if (!params[4].trim().startsWith("GO:"))
			{
				System.out.println("Error: " + readLine + " " + params[4]);
				System.exit(1);
			}
			String[] names = params[10].trim().split("[|]");
			String name = null;
			for(String nm : names)
			{
				if (geneNamesToIdMap.containsKey(nm))
				{
					name = nm;
					break;
				}
			}
			if (name != null)
			{
				ArrayList<String> lst = geneIdToGo.get(geneNamesToIdMap.get(name));
				if (lst == null)
				{
					lst = new ArrayList<String>();
				}
				lst.add(params[4]);
				geneIdToGo.put(geneNamesToIdMap.get(name), lst);
			}
			
			readLine = bufferedReader.readLine();
		}
		bufferedReader.close();
		return geneIdToGo;
	}

	private HashMap<String, ArrayList<String>> pathwayIdToGeneId()
			throws FileNotFoundException, IOException {
		BufferedReader bufferedReader;
		String readLine;
		bufferedReader = new BufferedReader(new FileReader(pathwayFile));
		HashMap<String, ArrayList<String>> pathwayIdtoGeneId = new HashMap<String, ArrayList<String>>();
		readLine = bufferedReader.readLine();
		while(readLine != null)
		{
			if (!readLine.startsWith("#") && !readLine.startsWith("UNIQUE-ID"))
			{
				readLine = readLine.trim();
				String params[] = readLine.split("\t");
				ArrayList<String> geneIds = pathwayIdtoGeneId.get(params[0].trim());
				if (geneIds == null)
				{
					geneIds = new ArrayList<String>();
				}
				for(int i = 120; i < params.length ; i++)
				{
					String geneId = params[i].trim();
					geneIds.add(geneId);
				}
				pathwayIdtoGeneId.put(params[0].trim(),geneIds);
			}
			readLine = bufferedReader.readLine();
		}
		bufferedReader.close();
		return pathwayIdtoGeneId;
	}

	private HashMap<String, ArrayList<String>> getPathwayToRxnMap()
			throws FileNotFoundException, IOException {
		HashMap<String, ArrayList<String>> pathwayToRxns = new HashMap<String, ArrayList<String>>();
		BufferedReader bufferedReader = new BufferedReader(new FileReader(pathwayDatFile));;
		String readLine = bufferedReader.readLine();
		String id_temp = null;
		ArrayList<String> rxns_temp = new ArrayList<String>();
		while(readLine != null)
		{
			if (readLine.startsWith("UNIQUE-ID"))
			{
				id_temp = readLine.split("UNIQUE-ID -")[1].trim();
			}
			else if (readLine.startsWith("REACTION-LIST"))
			{
				rxns_temp.add(readLine.split("REACTION-LIST -")[1].trim());
			}
			else if (readLine.startsWith("//"))
			{
				if (pathwayToRxns.containsKey(id_temp))
				{
					System.out.println("pathway id encountered twice " + id_temp);
					System.exit(1);
				}
				pathwayToRxns.put(id_temp, rxns_temp);
				id_temp = null;
				rxns_temp = new ArrayList<String>();
			}
			readLine = bufferedReader.readLine();
		}
		bufferedReader.close();
		return pathwayToRxns;
	}
	
//	private void readDataFile() throws IOException 
//	{
//		BufferedReader bufferedReader = new BufferedReader(new FileReader(dataFile));
//		String readLine = bufferedReader.readLine();
//		HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
//		while(readLine != null)
//		{
//			String[] params = readLine.split("\t");
//			if (!params[4].trim().startsWith("GO:"))
//			{
//				System.out.println("Error: " + readLine + " " + params[4]);
//				System.exit(1);
//			}
//			String id = params[1].split("-")[0].trim();
//			if (hashMap.containsKey(id))
//			{
//				ArrayList<String> lst = map.get(params[4].trim());
//				if (lst == null)
//				{
//					lst = new ArrayList<String>();
//				}
//				lst.add(id);
//				map.put(params[4].trim(), lst);
//			}
//			readLine = bufferedReader.readLine();
//		}
//		PrintWriter printWriter = new PrintWriter(outFile);
//		Set<String> set = map.keySet();
//		for(String key : set)
//		{
//			StringBuffer buffer = new StringBuffer();
//			ArrayList<String> lst = map.get(key);
//			for(String ky : lst)
//			{
//				buffer.append(ky + " ");
//			}
//			printWriter.println(key + "\t" + buffer.toString());
//		}
//		bufferedReader.close();
//		printWriter.flush();
//		printWriter.close();
//	}

	private String findParent(String goId) 
	{
		StringBuffer buffer = new StringBuffer();
		buffer.append(goId);
		while(true)
		{
			if (geneNamesToIdMap.containsKey(goId))
			{
				goId = geneNamesToIdMap.get(goId);
				buffer.append(" " + goId);
			}
			else
			{
				break;
			}
		}
		return buffer.toString();
	}

	@Override
	public void handleEvent(ParseEvents event) {
		switch((ParseEvents.EventTypes)event.getEventType())
		{
		case docStarted:
			if (this.flag)
			{
				this.geneNamesToIdMap = new HashMap<String, String>();
			}
			else
			{
				this.classIdToDescriptionMap = new HashMap<String, String>();
			}
			break;
		case filecommentLine:
			break;
		case uniqueIdLine:
		{
			String readLine = (String) event.getSource();
			this.id = readLine.split("UNIQUE-ID -")[1].trim();
			break;
		}
		case typesLine:
		{
			break;
		}
		case commonNameLine:
		{
			String readLine = (String) event.getSource();
			this.commonName = readLine.split("COMMON-NAME -")[1].trim();
			break;
		}
		case entrycomment:
		case entrycommentnewLine:
			break;
		case entrySeparator:
		{
			processEntry();
			break;
		}
		case docEnded : 
//			processMap();
			break;
		}
	}

	private void processMap() 
	{
		try
		{
			PrintWriter printWriter = new PrintWriter(this.outFile);
			Set<String> keySet = this.geneNamesToIdMap.keySet();
			for(String key : keySet)
			{
				printWriter.println(key + " " + this.geneNamesToIdMap.get(key));
			}
			printWriter.flush();
			printWriter.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

	private void processEntry() 
	{
		if (this.flag)
		{
			if (this.geneNamesToIdMap.containsKey(this.commonName))
			{
				System.out.println(this.commonName + " found two times in the file");
				System.exit(1);
			}
			else
			{
				geneNamesToIdMap.put(this.commonName, this.id);
			}
		}
		else
		{
			if(this.classIdToDescriptionMap.containsKey(this.id))
			{
				System.out.println(this.id + " found two times in the file");
				System.exit(1);
			}
			else
			{
				classIdToDescriptionMap.put(this.id, this.commonName);
			}
		}
		this.id = null;
		this.commonName = null;
	}
}
